﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Web.Configuration;
using System.Web.Http;
using System.Web.Http.Controllers;
using Common.Logging;
using In.Api.Dto.HisWs;
using Newtonsoft.Json;
using OutDbContext;
using User.Api.BizExtensions;
using User.Api.Dto.Book;
using User.Api.Helpers;
using User.Api.HttpClients;
using Rmq.Center;

namespace User.Api.Controllers
{
    public class BookController : ApiController
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(QueueController));
        private FsssdqfybjyEntities _ctx;
        private static readonly object OrderNoLocker = new object();

        protected override void Initialize(HttpControllerContext controllerContext)
        {
            _ctx = new FsssdqfybjyEntities();
            base.Initialize(controllerContext);
        }

        protected override void Dispose(bool disposing)
        {
            _ctx.Dispose();
            base.Dispose(disposing);
        }


        [HttpGet]
        [ActionName("GetBookDeptList")]
        public GetBookDeptListResponse GetBookDeptList()
        {
            var request = new Request4GetBookDeptList();

            Response4GetBookDeptList response4GetBookDeptList;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetBookDeptList", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4GetBookDeptList = responseMsg.Content.ReadAsAsync<Response4GetBookDeptList>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用GetBookDeptList api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetBookDeptListResponse
                {
                    ResultCode = "2",
                    ResultMsg = "服务器或网络异常，请联系客服！"
                };
            }

            if (response4GetBookDeptList.ResultCode != "0")
            {
                return new GetBookDeptListResponse
                {
                    ResultCode = "2",
                    ResultMsg = response4GetBookDeptList.ResultDesc
                };
            }

            var bookDeptList = response4GetBookDeptList.BookDeptList;
            var deptList = _ctx.Departs.Where(x => x.RecStatus == 1).ToList();
            var newDeptList = (from bd in bookDeptList
                join d in deptList on bd.DeptId equals d.DeptId into leftdept
                from left in leftdept.DefaultIfEmpty()
                select new GetBookDeptListResponse.Dept()
                {
                    BranchName = left == null ? "" : left.Loc,
                    DepartId = bd.DeptId,
                    DepartName = bd.DeptName
                }).OrderBy(x => x.DepartName).ToList();

            return new GetBookDeptListResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                Depts = newDeptList
            };
        }

        [HttpGet]
        [ActionName("GetBookDoctorList")]
        public GetBookDoctorListResponse GetBookDoctorList(string deptId)
        {
            var response4GetBookDoctorList = GetBookDoctorListById(deptId);
            if (response4GetBookDoctorList.ResultCode != "0")
            {
                return new GetBookDoctorListResponse
                {
                    ResultCode = "2",
                    ResultMsg = "服务器或网络异常，请联系客服！"
                };
            }

            var doctorPhotoBaseUrl = ConfigurationManager.AppSettings["DoctorPhotoWebUrl"];
            if (!doctorPhotoBaseUrl.EndsWith("/"))
            {
                doctorPhotoBaseUrl += "/";
            }
            //var doctorList = _ctx.Doctors.Where(x => x.DeptId == deptId && x.RecStatus == 1).ToList();
            //var doctorPhotoList = doctorList.ToDictionary(doctor => doctor.DoctorId, doctor => doctor.DoctorName);

            var bookDoctorList = response4GetBookDoctorList.BookDoctorList.GroupBy(x =>
                new {
                    x.DoctorId,
                    x.DoctorName,
                    x.RegType,
                    x.RegAmt
                })
                .Select(x =>
                new GetBookDoctorListResponse.DoctorInfo
                {
                    DoctorId = x.Key.DoctorId,
                    DoctorName = x.Key.DoctorName,
                    //DoctorPic = doctorPhotoList.Keys.Contains(x.Key.DoctorId) 
                    //    ? doctorPhotoBaseUrl + x.Key.DoctorName + ".JPG" : doctorPhotoBaseUrl + "doctorNoPhoto.jpg",
                    DoctorPic = doctorPhotoBaseUrl + x.Key.DoctorName + ".JPG",
                    RegType = x.Key.RegType,
                    RegAmt = x.Key.RegAmt,
                    LeaveCount = x.Sum(y => y.BookLimit.ToInt32OrDefault() - y.BookCount.ToInt32OrDefault()),
                }).Where(x => x.LeaveCount > 0).ToList();


            return new GetBookDoctorListResponse()
            {
                ResultCode = "0",
                ResultMsg = "",
                Doctors = bookDoctorList
            };
        }

        [HttpGet]
        [ActionName("GetBookDoctorScheduleList")]
        public GetBookDoctorScheduleListResponse GetBookDoctorScheduleList(string deptId, string doctorId, string doctorName, string regType)
        {
            var response4GetBookDoctorList = GetBookDoctorListById(deptId);
            if (response4GetBookDoctorList.ResultCode != "0")
            {
                return new GetBookDoctorScheduleListResponse
                {
                    ResultCode = "2",
                    ResultMsg = "服务器或网络异常，请联系客服！"
                };
            }
            
            var doctorScheduleList =
                response4GetBookDoctorList.BookDoctorList.Where(x => x.DoctorId == doctorId)
                    .Select(x => new GetBookDoctorScheduleListResponse.Schedule
                    {
                        ScheduleId = x.ScheduleId,
                        SubjectId = x.SubjectId,
                        SubjectName = x.SubjectName,
                        RegType = x.RegType,
                        RegAmt = x.RegAmt,
                        StartTime = x.StartTime,
                        EndTime = x.EndTime,
                        LeaveCount = x.BookLimit.ToInt32() - x.BookCount.ToInt32(),
                    }).Where(x => x.LeaveCount > 0).ToList();
            
            //if (!string.IsNullOrEmpty(regType))
            //{
            //    doctorScheduleList = doctorScheduleList.Where(x => x.RegType == regType).ToList();
            //}

            var doctorPhotoBaseUrl = ConfigurationManager.AppSettings["DoctorPhotoWebUrl"];
            if (!doctorPhotoBaseUrl.EndsWith("/"))
            {
                doctorPhotoBaseUrl += "/";
            }
            var doctorPhotoUrl = doctorPhotoBaseUrl + doctorName + ".JPG"; 
            return new GetBookDoctorScheduleListResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                DoctorId = doctorId,
                DoctorName = doctorName,
                DoctorPic = doctorPhotoUrl,
                Schedules = doctorScheduleList
            };
        }

        [HttpGet]
        [ActionName("GetBookDoctorTimeTable")]
        public GetBookDoctorTimeTableResponse GetBookDoctorTimeTable(string parentScheduleId, string doctorId, string startTime, string endTime)
        {
            var request = new Request4GetBookDoctorTimeTable();
            request.ScheduleId = parentScheduleId;
            request.DoctorId = doctorId;
            request.StartDate = startTime;
            request.EndDate = endTime;

            Response4GetBookDoctorTimeTable response4GetBookDoctorTimeList;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetBookDoctorTimeTable", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4GetBookDoctorTimeList = responseMsg.Content.ReadAsAsync<Response4GetBookDoctorTimeTable>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用GetBookDoctorList api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetBookDoctorTimeTableResponse
                {
                    ResultCode = "2",
                    ResultMsg = "服务器或网络异常，请联系客服！"
                };
            }

            if (response4GetBookDoctorTimeList.ResultCode != "0")
            {
                return new GetBookDoctorTimeTableResponse
                {
                    ResultCode = "2",
                    ResultMsg = response4GetBookDoctorTimeList.ResultDesc
                };
            }

            var doctorTimeList = 
                response4GetBookDoctorTimeList.BookDoctorTimeList.Select(x => new GetBookDoctorTimeTableResponse.DoctorTime
                {
                    ScheduleId = x.ScheduleId,
                    SpanStartTime = x.SpanStartTime,
                    SpanEndTime = x.SpanEndTime,
                    LeaveCount = x.BookLimit.ToInt32OrDefault() - x.BookCount.ToInt32OrDefault()
                }).Where(x => x.LeaveCount > 0).ToList();

            return new GetBookDoctorTimeTableResponse()
            {
                ResultCode = "0",
                ResultMsg = "",
                DoctorTimes = doctorTimeList
            };
        }


        public Response4GetBookDoctorList GetBookDoctorListById(string deptId)
        {
            var request = new Request4GetBookDoctorList();
            request.DeptId = deptId;
            Response4GetBookDoctorList response4GetBookDoctorList;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetBookDoctorList", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4GetBookDoctorList = responseMsg.Content.ReadAsAsync<Response4GetBookDoctorList>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用 GetBookDoctorList api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new Response4GetBookDoctorList
                {
                    ResultCode = "2",
                };
            }

            if (response4GetBookDoctorList.ResultCode != "0")
            {
                return new Response4GetBookDoctorList
                {
                    ResultCode = "2",
                };
            }

            //if (DateTime.Now.Hour >= 16)
            //{
            //    var dtTwoDaysLater = DateTime.Now.AddDays(2).ToString("yyyy-MM-dd");
            //    response4GetBookDoctorList.BookDoctorList =
            //        response4GetBookDoctorList.BookDoctorList.Where(x =>
            //        string.Compare(x.StartTime, dtTwoDaysLater, StringComparison.Ordinal) > 0).ToList();
            //}

            return response4GetBookDoctorList;
        }

        [HttpGet]
        [ActionName("CreateBookOrder")]
        public CreateBookOrderResponse CreateBookOrder(int cardId, string deptId, string deptName, string doctorId, string doctorName, string parentScheduleId, string scheduleId,
            string subjectId, string spanStartTime, string spanEndTime, string regAmt, string regType, string bookCellphone)
        {
            var azUser = AzUser.GetInApi(Request);
            var card = _ctx.HospCards.Where(x => x.Id == cardId && x.WxUserId == azUser.UserId)
                .Select(x => new
                {
                    x.CardNo,
                    x.PatientName,
                    x.Phone
                }).FirstOrDefault();
            if (card == null)
            {
                return new CreateBookOrderResponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到诊疗号信息"
                };
            }

            var failBookMsg = "";
            var canBook = CanBook(card.CardNo, out failBookMsg);
            if (!canBook)
            {
                return new CreateBookOrderResponse
                {
                    ResultCode = "1",
                    ResultMsg = failBookMsg
                };
            }

            //新建订单
            var bookOrder = new BookOrder
            {
                WxUserId = azUser.UserId,
                CardNo = card.CardNo,
                CardName = card.PatientName,
                Phone = bookCellphone,
                DeptId = deptId,
                DeptName = deptName,
                DoctorId = doctorId,
                DoctorName = doctorName,
                ParentScheduleId = parentScheduleId,
                ScheduleId = scheduleId,
                RegType = regType,
                RegAmt = regAmt.ToDecimalOrDefault(),
                SubjectId = subjectId,
                BookStartTime = spanStartTime,
                BookEndTime = spanEndTime,
                RegistrarId = "008881",
                MachineId = "008881",
                BookStatus = BookOrderExtensions.BookStatus.未发起预约.ToInt32(),
                CreateTime = DateTime.Now,
            };

            _ctx.BookOrders.Add(bookOrder);
            _ctx.SaveChanges();

            if (card.Phone != bookOrder.Phone)
            {
                var getClinPatientInfoResponse = new CardController().GetClinPatientInfo(card.CardNo);
                if (getClinPatientInfoResponse.ResultCode != "0")
                {
                    return new CreateBookOrderResponse
                    {
                        ResultCode = "1",
                        ResultMsg = getClinPatientInfoResponse.ResultMsg
                    };
                }

                var clinPatientInfo = getClinPatientInfoResponse.ClinPatientInfo;

                //编辑门诊病人信息（手机号）
                var request4EditClinPatient = new Request4EditClinPatient();
                request4EditClinPatient.HosPatId = clinPatientInfo.HosPatId;
                request4EditClinPatient.Name = clinPatientInfo.Name;
                request4EditClinPatient.Sex = clinPatientInfo.Sex;
                request4EditClinPatient.BirthDay = clinPatientInfo.BirthDay;
                request4EditClinPatient.IdCard = clinPatientInfo.IdCard;
                request4EditClinPatient.FamilyAddress = clinPatientInfo.FamilyAddress;
                request4EditClinPatient.FamilyPhone = clinPatientInfo.FamilyPhone;
                request4EditClinPatient.ClinNo = clinPatientInfo.ClinNo;
                request4EditClinPatient.CardNo = clinPatientInfo.ClinNo;
                request4EditClinPatient.PayType = clinPatientInfo.PayType;
                request4EditClinPatient.KeyField = string.IsNullOrEmpty(clinPatientInfo.IdCard) ? "CardNo" : "IdCard";
                request4EditClinPatient.Phone = bookOrder.Phone;

                Response4EditClinPatient response4EditClinPatient;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("HisWs/EditClinPatient", request4EditClinPatient).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    response4EditClinPatient = responseMsg.Content.ReadAsAsync<Response4EditClinPatient>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内EditClinPatient Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    return new CreateBookOrderResponse
                    {
                        ResultCode = "3",
                        ResultMsg = "服务器或网络异常，请联系客服"
                    };
                }

                if (response4EditClinPatient.ResultCode != "0")
                {
                    return new CreateBookOrderResponse
                    {
                        ResultCode = "4",
                        ResultMsg = response4EditClinPatient.ResultDesc
                    };
                }
            }

            //提交预约信息
            var request = new Request4SaveBookInfo();
            request.HosPatId = "";
            request.ClinNo = "";
            request.IdCard = "";
            request.CardNo = bookOrder.CardNo;
            request.Phone = bookOrder.Phone;
            request.ScheduleId = bookOrder.ScheduleId;
            request.DeptId = bookOrder.DeptId;
            request.DoctorId = bookOrder.DoctorId;
            request.SubjectId = bookOrder.SubjectId;
            request.BookStartTime = bookOrder.BookStartTime;
            request.BookEndTime = bookOrder.BookEndTime;
            request.RegistrarId = bookOrder.RegistrarId;
            request.MachineId = bookOrder.MachineId;

            Response4SaveBookInfo response4SaveBookInfo;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/SaveBookInfo", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4SaveBookInfo = responseMsg.Content.ReadAsAsync<Response4SaveBookInfo>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内SaveBookInfo Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                return new CreateBookOrderResponse
                {
                    ResultCode = "3",
                    ResultMsg = "服务器或网络异常，请联系客服"
                };
            }

            if (response4SaveBookInfo.ResultCode != "0")
            {
                return new CreateBookOrderResponse
                {
                    ResultCode = "4",
                    ResultMsg = response4SaveBookInfo.ResultDesc
                };
            }

            var flowNo = response4SaveBookInfo.FlowNo;
            var bookNo = response4SaveBookInfo.BookNo;
            var bookTime = response4SaveBookInfo.BookTime;

            bookOrder.BookStatus = 1;
            bookOrder.ErrorMsg = "";
            bookOrder.FlowNo = flowNo;
            bookOrder.BookNo = bookNo;
            bookOrder.BookTime = bookTime;

            var apptAttnLog = new ApptAttnLog
            {
                WxUserId = bookOrder.WxUserId,
                BkMemberId = bookOrder.BkMemberId,
                OrderId = bookOrder.Id,
                PatientName = "",
                RegDate = bookOrder.BookStartTime.Substring(0, 10),
                TimeSlice = bookOrder.BookStartTime.Substring(11, 8) + "-" + bookOrder.BookEndTime.Substring(11, 8),
                DeptName = bookOrder.DeptName,
                HospName = "广东医科大学附属妇女儿童医院",
                CardNo = bookOrder.CardNo
            };
            apptAttnLog.NeedToSendTime1 = DateTime.Parse(DateTime.Parse(apptAttnLog.RegDate).AddDays(-1).ToString("yyyy-MM-dd") + " " + "18:00:00"); //前一天发送
            apptAttnLog.NeedToSendTime2 = DateTime.Parse(bookOrder.BookStartTime).AddHours(-1); //提前一小时
            apptAttnLog.RecCreateDt = DateTime.Now;
            apptAttnLog.SendTimes = DateTime.Now > apptAttnLog.SendTime1 ? 1 : 0;

            _ctx.ApptAttnLogs.Add(apptAttnLog);

            _ctx.SaveChanges();

            // RMQ 发送通知
            var userMessageProducer = new UserMessageProducer();
            userMessageProducer.Publish(new UserMessageMsg
            {
                Type = UserMessageType.预约成功通知,
                OrderId = bookOrder.Id.ToInt32()
            });

            return new CreateBookOrderResponse()
            {
                ResultCode = "0",
                ResultMsg = "",
                BookNo = bookNo
            };
        }

        /// <summary>
        /// 能否预约
        /// </summary>
        /// <param name="cardNo"></param>
        /// <param name="failMsg"></param>
        /// <returns></returns>
        private bool CanBook(string cardNo, out string failMsg)
        {
            failMsg = "";
            var now = DateTime.Now;
            var firstDayOfThisMonth = new DateTime(now.Year, now.Month, 1);
            var startDate = firstDayOfThisMonth.ToString("yyyy-MM-dd");
            var endDate = firstDayOfThisMonth.AddMonths(1).ToString("yyyy-MM-dd");

            var request = new Request4GetBookInfo();
            request.HosPatId = "";
            request.ClinNo = "";
            request.IdCard = "";
            request.CardNo = cardNo;
            request.FlowNo = "";
            request.StartDate = startDate;
            request.EndDate = endDate;

            Response4GetBookInfo response4GetGetBookInfo;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetBookInfo", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4GetGetBookInfo = responseMsg.Content.ReadAsAsync<Response4GetBookInfo>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内GetBookInfo Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                failMsg = "服务器或网络异常，请联系客服";
                return false;
            }

            if (response4GetGetBookInfo.ResultCode != "0")
            {
                failMsg = response4GetGetBookInfo.ResultDesc;
                return false;
            }

            //const int limitCount = 3;
            //var noCheckInCount = response4GetGetBookInfo.BookInfoList.Count(x => x.State == "未生效");
            //if (noCheckInCount >= limitCount)
            //{
            //    failMsg = $"本月预约未报到次数已达到{limitCount}次，本月不能再次预约";
            //    return false;
            //}

            return true;
        }

        /// <summary>
        /// 获取预约记录
        /// </summary>
        /// <param name="cardNo"></param>
        /// <param name="startDate"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetBookInfo")]
        public GetBookInfoResponse GetBookInfo(string cardNo, string startDate)
        {
            var request = new Request4GetBookInfo();
            request.HosPatId = "";
            request.ClinNo = "";
            request.IdCard = "";
            request.CardNo = cardNo;
            request.FlowNo = "";
            request.StartDate = startDate;
            request.EndDate = startDate.ToDateTimeOrDefault().AddDays(15).ToString("yyy-MM-dd");

            Response4GetBookInfo response4GetGetBookInfo;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetBookInfo", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4GetGetBookInfo = responseMsg.Content.ReadAsAsync<Response4GetBookInfo>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内GetBookInfo Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetBookInfoResponse
                {
                    ResultCode = "2",
                    ResultMsg = "服务器或网络异常，请联系客服"
                };
            }

            if (response4GetGetBookInfo.ResultCode != "0")
            {
                return new GetBookInfoResponse
                {
                    ResultCode = "2",
                    ResultMsg = response4GetGetBookInfo.ResultDesc
                };
            }

            if (response4GetGetBookInfo.BookInfoList.Count == 0)
            {
                return new GetBookInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = "未找到相关记录"
                };
            }

            var bookOrderList = new List<BookOrder>();
            foreach (var bookInfo in response4GetGetBookInfo.BookInfoList)
            {
                if (bookInfo.State == "未生效" && bookInfo.BookEndTime.ToDateTimeOrDefault() > DateTime.Now)
                {
                    if (_ctx.BookOrders.Any(x => x.FlowNo == bookInfo.FlowNo) == false)
                    {
                        //新建订单
                        var bookOrder = new BookOrder
                        {
                            WxUserId = null,//设为null值，用于标识为非微信预约订单
                            FlowNo = bookInfo.FlowNo,
                            BookNo = bookInfo.BookNo,
                            BookTime = bookInfo.BookTime.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                            CardNo = bookInfo.CardNo,
                            CardName = "",
                            Phone = "",
                            DeptId = bookInfo.DeptId,
                            DeptName = bookInfo.DeptName,
                            DoctorId = bookInfo.DoctorId,
                            DoctorName = bookInfo.DoctorName,
                            ParentScheduleId = "",
                            ScheduleId = bookInfo.ScheduleId,
                            RegType = bookInfo.RegType,
                            RegAmt = null,
                            SubjectId = bookInfo.SubjectId,
                            BookStartTime = bookInfo.BookStartTime.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                            BookEndTime = bookInfo.BookEndTime.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                            RegistrarId = "",
                            MachineId = "",
                            BookStatus = BookOrderExtensions.BookStatus.预约成功.ToInt32(),
                            CreateTime = DateTime.Now,
                        };
                        bookOrderList.Add(bookOrder);
                    }
                }
            }
            if (bookOrderList.Count > 0)
            {
                _ctx.BookOrders.AddRange(bookOrderList);
                _ctx.SaveChanges();
            }

            var bookInfoList = response4GetGetBookInfo.BookInfoList.Select(x => new GetBookInfoResponse.BookInfo()
            {
                FlowNo = x.FlowNo,
                BookNo = x.BookNo,
                DeptName = x.DeptName,
                DoctorName = x.DoctorName,
                RegType = x.RegType,
                BookStartTime = x.BookStartTime,
                BookEndTime = x.BookEndTime,
                BookTime = Convert.ToDateTime(x.BookTime).ToString("yyyy-MM-dd HH:mm:ss"),
                State = x.State,
                CanCancelBook = JudgeCanCancelBook(x.State, x.BookStartTime),
                CanCheckIn = JudgeCanCheckIn(x.State, x.BookStartTime)
            }).OrderByDescending(x => x.BookTime).ToList();

            return new GetBookInfoResponse()
            {
                ResultCode = "0",
                ResultMsg = "",
                BookInfos = bookInfoList
            };
        }


        /// <summary>
        /// 判断能否取消预约
        /// </summary>
        /// <param name="state"></param>
        /// <param name="bookStartTime"></param>
        /// <returns></returns>
        private bool JudgeCanCancelBook(string state, string bookStartTime)
        {
            if (state == "未生效")
            {
                var dBookStartTime = bookStartTime.ToDateTimeOrDefault();
                if (dBookStartTime > DateTime.Now)
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 判断能否报到
        /// </summary>
        /// <param name="state"></param>
        /// <param name="bookStartTime"></param>
        /// <returns></returns>
        private bool JudgeCanCheckIn(string state, string bookStartTime)
        {
            if (state == "未生效")
            {
                var dBookStartTime = bookStartTime.ToDateTimeOrDefault();
                if (dBookStartTime.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd"))
                {
                    //if (dBookStartTime.Hour < 12)
                    //{
                    //    return true;
                    //}

                    if (dBookStartTime.AddMilliseconds(15) > DateTime.Now)
                    {
                        return true;
                    }
                }

                //var checkInPmTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd") + " 13:45:00");
                //if (DateTime.Now > checkInPmTime)
                //{
                //    return true;
                //}
            }

            return false;
        }

        [HttpGet]
        [ActionName("CancelBook")]
        public CancelBookResponse CancelBook(string flowNo)
        {
            var request = new Request4CancelBookInfo();
            request.FlowNo = flowNo;
            request.RegistrarId = "008881";
            request.MachineId = "008881";

            Response4CancelBookInfo response4CancelBookInfo;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/CancelBookInfo", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4CancelBookInfo = responseMsg.Content.ReadAsAsync<Response4CancelBookInfo>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内CancelBookInfo Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new CancelBookResponse
                {
                    ResultCode = "2",
                    ResultMsg = "服务器或网络异常，请联系客服"
                };
            }

            var order = _ctx.BookOrders.Where(x => x.FlowNo == flowNo).OrderByDescending(x => x.Id).FirstOrDefault();
            if (response4CancelBookInfo.ResultCode != "0")
            {
                if (order != null)
                {
                    order.BookStatus = 4;
                    order.ErrorMsg = response4CancelBookInfo.ResultDesc;

                    _ctx.SaveChanges();
                }

                return new CancelBookResponse
                {
                    ResultCode = "2",
                    ResultMsg = response4CancelBookInfo.ResultDesc
                };
            }

            if (order != null)
            {
                order.BookStatus = 3;
                order.ErrorMsg = "";
                _ctx.SaveChanges();

                // RMQ 发送通知
                var userMessageProducer = new UserMessageProducer();
                userMessageProducer.Publish(new UserMessageMsg
                {
                    Type = UserMessageType.取消预约成功通知,
                    OrderId = order.Id.ToInt32()
                });
            }

            return new CancelBookResponse()
            {
                ResultCode = "0",
                ResultMsg = ""
            };
        }


        /// <summary>
        /// 预约报到生成挂号订单
        /// </summary>
        /// <param name="flowNo">预约流水号</param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("CreateRegOrder")]
        public CreateRegOrderResponse CreateRegOrder(string flowNo)
        {
            var azUser = AzUser.GetInApi(Request);
            using (var ctx = new FsssdqfybjyEntities())
            {
                var Order = ctx.ApptOrders.FirstOrDefault(x => x.RegNo == flowNo && x.OrderStatus == 21);
                if(Order != null)
                {
                    return new CreateRegOrderResponse
                    {
                        ResultCode = "1",
                        ResultMsg = "请勿重复报道"
                    };
                }
                var bookOrder = ctx.BookOrders.FirstOrDefault(x => x.FlowNo == flowNo && x.BookStatus == 1);
                if (bookOrder == null)
                {
                    return new CreateRegOrderResponse
                    {
                        ResultCode = "1",
                        ResultMsg = "没有找到您的预约信息"
                    };
                }

                if (DateTime.Parse(bookOrder.BookEndTime) < DateTime.Now.AddMinutes(-15))
                {
                    return new CreateRegOrderResponse
                    {
                        ResultCode = "1",
                        ResultMsg = "您的预约已过期"
                    };
                }

                if (DateTime.Now < DateTime.Parse(DateTime.Now.ToShortDateString() + " 12:00:00")&& DateTime.Parse(bookOrder.BookEndTime)> DateTime.Parse(DateTime.Now.ToShortDateString() + " 12:00:00"))
                {
                    return new CreateRegOrderResponse
                    {
                        ResultCode = "1",
                        ResultMsg = "未到报道时间"
                    };
                }


                var hospCard = ctx.HospCards.FirstOrDefault(x => x.CardNo == bookOrder.CardNo && x.RecStatus == 1);
                if (hospCard == null)
                {
                    return new CreateRegOrderResponse
                    {
                        ResultCode = "1",
                        ResultMsg = "没有查找您的卡信息"
                    };
                }

                var isExistsOrder = false;

                #region 查询订单
                var apptOrder = ctx.ApptOrders.FirstOrDefault(x => x.RegNo == bookOrder.FlowNo &&
                                                (x.OrderStatus == 13 || x.OrderStatus == 16));
                if (apptOrder != null)
                {
                    isExistsOrder = false;
                    if (apptOrder.OrderStatus == ApptOrderExtensions.OrderStatus.支付中.ToInt32())  //支付中，令支付失败
                    {
                        apptOrder.OrderStatus = ApptOrderExtensions.OrderStatus.支付失败.ToInt32();
                        apptOrder.NextCheckTime = null;
                        apptOrder.OrderStatusOnSetCheck = null;
                        ctx.SaveChanges();
                    }
                    else if (apptOrder.OrderStatus == ApptOrderExtensions.OrderStatus.取号中.ToInt32()) //取号中，需要等待
                    {
                        isExistsOrder = true;
                    }
                }
                if (isExistsOrder)
                {
                    return new CreateRegOrderResponse
                    {
                        ResultCode = "1",
                        ResultMsg = "您的订单正在处理中，请稍候留意消息通知"
                    };
                }
                #endregion

                #region 查询挂号费
                var request4GetRegAmt = new Request4GetRegAmt();
                request4GetRegAmt.HosPatId = hospCard.PatientId;
                request4GetRegAmt.CardNo = hospCard.CardNo;
                request4GetRegAmt.IdCard = "";
                request4GetRegAmt.ClinNo = "";
                request4GetRegAmt.ScheduleId = bookOrder.ScheduleId;
                request4GetRegAmt.DeptId = bookOrder.DeptId;
                request4GetRegAmt.DoctorId = bookOrder.DoctorId;
                request4GetRegAmt.SubjectId = "";

                Response4GetRegAmt response4GetRegAmt;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetRegAmt", request4GetRegAmt).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    response4GetRegAmt = responseMsg.Content.ReadAsAsync<Response4GetRegAmt>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内GetRegAmt Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                    return new CreateRegOrderResponse
                    {
                        ResultCode = "2",
                        ResultMsg = "服务器或网络异常，请联系客服"
                    };
                }

                if (response4GetRegAmt.ResultCode != "0")
                {
                    return new CreateRegOrderResponse
                    {
                        ResultCode = "1",
                        ResultMsg = response4GetRegAmt.ResultDesc
                    };
                }
                if (string.IsNullOrEmpty(response4GetRegAmt.RegAmt))
                {
                    return new CreateRegOrderResponse
                    {
                        ResultCode = "1",
                        ResultMsg = "获取挂号费用异常，请联系客服"
                    };
                }

                var regAmt = response4GetRegAmt.RegAmt.ToDecimalOrDefault();
                #endregion

                #region 生成订单

                var orderType = bookOrder.WxUserId.HasValue
                    ? ApptOrderExtensions.OrderType.预约.ToInt32().ToString()
                    : ApptOrderExtensions.OrderType.其它平台预约.ToInt32().ToString();
                var orderNo = GenerateNewOrderNo();
                var order = new ApptOrder
                {
                    WxUserId = azUser.UserId,
                    OrderType = orderType,
                    RegNo = bookOrder.FlowNo,  //预约流水号
                    CardNo = bookOrder.CardNo,
                    CardName = hospCard.Name,
                    DeptId = bookOrder.DeptId,
                    DeptName = bookOrder.DeptName,
                    DoctorId = bookOrder.DoctorId ?? "",
                    DoctorName = bookOrder.DoctorName ?? "",
                    ScheduleId = bookOrder.ScheduleId ?? "",
                    SubjectId = bookOrder.SubjectId ?? "",
                    SbConfirmed = "0",
                    OrderNo = orderNo,
                    RegDate = bookOrder.BookStartTime.Substring(0, 10),// DateTime.Now.ToString("yyyy-MM-dd"),
                    OrderStatus = ApptOrderExtensions.OrderStatus.预约成功.ToInt32(),
                    TimeSlice = "",
                    StartTime = bookOrder.BookStartTime.Substring(11, 5),
                    EndTime = bookOrder.BookEndTime.Substring(11, 5),
                    RegType = bookOrder.RegType ?? "普通挂号",
                    PayState = ApptOrderExtensions.PayState.未付款.ToInt32().ToString(),
                    Fee = regAmt,
                    TreatFee = null,
                    OtherFee = null,
                    SumFee = regAmt,
                    CreateTime = DateTime.Now,
                    NextCheckTime = null,
                };

                ctx.ApptOrders.Add(order);
                ctx.SaveChanges();
                #endregion

                // 费用为0的直接设置为支付成功
                if (order.SumFee == 0)
                {
                    order.PayState = ApptOrderExtensions.PayState.已付款.ToInt32().ToString();
                    order.PayTime = DateTime.Now;
                    order.WxTransactionId = "0";
                    order.OrderStatus = ApptOrderExtensions.OrderStatus.支付成功.ToInt32();
                    ctx.SaveChanges();

                    // RMQ 执行取号
                    var pickupingProducer = new OrderPickupingProducer();
                    pickupingProducer.Publish(new OrderPickupingMsg
                    {
                        OrderType = OrderType.挂号订单,
                        OrderId = order.Id
                    });

                    return new CreateRegOrderResponse
                    {
                        ResultCode = "0",
                        ResultMsg = "",
                        OrderId = order.Id,
                        OrderNo = order.OrderNo,
                        PayString = ""
                    };
                }

                order.OrderStatus = ApptOrderExtensions.OrderStatus.支付中.ToInt32();
                ctx.SaveChanges();

                // RMQ 16分钟后如果还是支付中则设置支付失败
                var payingTimeoutProducer = new OrderPayingTimeoutProducer();
                payingTimeoutProducer.Publish(new OrderPayingTimeoutMsg
                {
                    OrderType = OrderType.挂号订单,
                    OrderId = order.Id
                }, 16 * 60 * 1000);

                //组织 微信 js 支付方法 getBrandWCPayRequest 的参数
                var payStartTime = System.DateTime.Now.ToString("yyyyMMddHHmmss");
                var payExpireTime = System.DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss");

                var payFee = (order.SumFee * 100).ToInt32().ToString();
                var superWxUserIds = WebConfigurationManager.AppSettings["UserIdsForPayMin"].Split(" , ",
                StringSplitOptions.RemoveEmptyEntries);
                if (order.WxUserId.HasValue && superWxUserIds.Contains(order.WxUserId.ToStringOrDefault()))
                {
                    payFee = "1";
                }

                var result = WeixinPayV3Helper.ComposeJsApiParameter("就诊挂号", "AP" + order.OrderNo,
                  payFee, GetClientIp(), payStartTime, payExpireTime, "Reg/PaySucceed", azUser.OpenId);

                if (result.ResultCode != "0")
                {
                    return new CreateRegOrderResponse
                    {
                        ResultCode = "1",
                        ResultMsg = result.ResultMsg
                    };
                }

                return new CreateRegOrderResponse
                {
                    ResultCode = "0",
                    ResultMsg = "",
                    OrderId = order.Id,
                    OrderNo = order.OrderNo,
                    PayString = result.Parameter
                };
            }
        }


        /// <summary>
        /// 生成挂号订单号
        /// </summary>
        /// <returns></returns>
        public string GenerateNewOrderNo()
        {
            var orderNo = "WX" + DateTime.Now.Date.ToString("yyyyMMdd");
            lock (OrderNoLocker)
            {
                orderNo += (DateTime.Now - DateTime.Now.Date).TotalMilliseconds.ToString("00000000");
                Thread.Sleep(1);
            }

            return orderNo;
        }


        public string GetClientIp()
        {
            if (Request.Properties.ContainsKey("MS_HttpContext"))
            {
                string ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                //判断是否有代理服务器
                if (string.IsNullOrEmpty(ip))
                {
                    //没有代理服务器,如果有代理服务器获取的是代理服务器的IP
                    ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                }

                string pattrn = @"(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])";
                if (!string.IsNullOrEmpty(ip) && System.Text.RegularExpressions.Regex.IsMatch(ip, pattrn))
                {
                    return ip;
                }

                return "127.0.0.1";
            }
            else
            {
                return "127.0.0.1";
            }
        }
    }
}
